﻿using Microsoft.EntityFrameworkCore;

namespace Devonline.Identity;

/// <summary>
/// 重载的身份上下文, 提供字符串类型主键的默认实现
/// </summary>
public class SecurityIdentityDbContext : SecurityIdentityDbContext<User, Role, UserClaim, UserRole, UserLogin, RoleClaim, UserToken, Group, UserGroup, Level, Resource, AccessRule, AccessApply, AccessRecord, Parameter, Attachment, Secret, UserSecret, ResourceSecret, string>
{
    public SecurityIdentityDbContext(DbContextOptions<IdentityDbContext> options) : base(options) { }
}

/// <summary>
/// 重载的身份上下文, 提供字符串类型主键的默认实现
/// </summary>
public class SecurityIdentityDbContext<TKey> : SecurityIdentityDbContext<User<TKey>, Role<TKey>, UserClaim<TKey>, UserRole<TKey>, UserLogin<TKey>, RoleClaim<TKey>, UserToken<TKey>, Group<TKey>, UserGroup<TKey>, Level<TKey>, Resource<TKey>, AccessRule<TKey>, AccessApply<TKey>, AccessRecord<TKey>, Parameter<TKey>, Attachment<TKey>, Secret<TKey>, UserSecret<TKey>, ResourceSecret<TKey>, TKey>
    where TKey : IEquatable<TKey>, IConvertible
{
    public SecurityIdentityDbContext(DbContextOptions<IdentityDbContext<TKey>> options) : base(options) { }
}

/// <summary>
/// 重载的安全身份上下文
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TRole"></typeparam>
/// <typeparam name="TUserClaim"></typeparam>
/// <typeparam name="TUserRole"></typeparam>
/// <typeparam name="TUserLogin"></typeparam>
/// <typeparam name="TRoleClaim"></typeparam>
/// <typeparam name="TUserToken"></typeparam>
/// <typeparam name="TGroup"></typeparam>
/// <typeparam name="TUserGroup"></typeparam>
/// <typeparam name="TLevel"></typeparam>
/// <typeparam name="TResource"></typeparam>
/// <typeparam name="TAccessRule"></typeparam>
/// <typeparam name="TAccessApply"></typeparam>
/// <typeparam name="TAccessRecord"></typeparam>
/// <typeparam name="TParameter"></typeparam>
/// <typeparam name="TAttachment"></typeparam>
/// <typeparam name="TSecret"></typeparam>
/// <typeparam name="TResourceSecret"></typeparam>
/// <typeparam name="TKey"></typeparam>
public class SecurityIdentityDbContext<TUser, TRole, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken, TGroup, TUserGroup, TLevel, TResource, TAccessRule, TAccessApply, TAccessRecord, TParameter, TAttachment, TSecret, TUserSecret, TResourceSecret, TKey> :
    IdentityDbContext<TUser, TRole, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken, TGroup, TUserGroup, TLevel, TResource, TAccessRule, TAccessApply, TAccessRecord, TParameter, TAttachment, TKey>
    where TUser : User<TKey>
    where TRole : Role<TKey>
    where TUserClaim : UserClaim<TKey>
    where TUserRole : UserRole<TKey>
    where TUserLogin : UserLogin<TKey>
    where TRoleClaim : RoleClaim<TKey>
    where TUserToken : UserToken<TKey>
    where TGroup : Group<TKey>
    where TUserGroup : UserGroup<TKey>
    where TLevel : Level<TKey>
    where TResource : Resource<TKey>
    where TAccessRule : AccessRule<TKey>
    where TAccessApply : AccessApply<TKey>
    where TAccessRecord : AccessRecord<TKey>
    where TParameter : Parameter<TKey>
    where TAttachment : Attachment<TKey>
    where TSecret : Secret<TKey>
    where TUserSecret : UserSecret<TKey>
    where TResourceSecret : ResourceSecret<TKey>
    where TKey : IEquatable<TKey>, IConvertible
{
    public SecurityIdentityDbContext(DbContextOptions options) : base(options) { }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.Entity<TSecret>(b =>
        {
            b.Property(x => x.State).HasDefaultValue(DataState.Available);
            b.Property(x => x.IdentityType).HasDefaultValue(IdentityType.User);
            b.Property(x => x.HashAlgorithm).HasDefaultValue(HashAlgorithm.SHA256);
            b.Property(x => x.SymmetricAlgorithm).HasDefaultValue(SymmetricAlgorithm.AES_256_CBC);
            b.Property(x => x.AsymmetricAlgorithm).HasDefaultValue(EncryptionAlgorithm.RSA);
        });

        builder.Entity<TUserSecret>(b => b.Property(x => x.State).HasDefaultValue(DataState.Available));
        builder.Entity<TResourceSecret>(b => b.Property(x => x.State).HasDefaultValue(DataState.Available));
    }

    #region identity core entities
    /// <summary>
    /// Secret
    /// </summary>
    public virtual DbSet<TSecret> Secrets { get; set; }
    /// <summary>
    /// UserSecret
    /// </summary>
    public virtual DbSet<TUserSecret> UserSecrets { get; set; }
    /// <summary>
    /// ResourceSecret
    /// </summary>
    public virtual DbSet<TResourceSecret> ResourceSecrets { get; set; }
    #endregion
}